package com.example.discard.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * 处理服务器端channel
 * <p>
 * DiscardServerHandler扩展了ChannelInboundHandlerAdapter，它是ChannelInboundHandler的一个实现。
 * ChannelInboundHandler提供了各种可以覆盖的事件处理程序方法。
 * 现在，扩展ChannelInboundHandlerAdapter就足够了，而不是自己实现处理程序接口。
 *
 * @author linfeng
 * @date 2021/12/15 14:14
 */
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 我们在这里重写channelRead()事件处理程序方法。每当从客户端接收到新数据时，都会用接收到的消息调用此方法。在这个例子中，接收到的消息的类型是ByteBuf。
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 要实现丢弃协议，处理程序必须忽略收到的消息。
        // ByteBuf是一个引用计数的对象，必须通过release()方法显式释放。
        // 请记住，释放传递给handler的任何引用计数的对象是handler的责任。
        ByteBuf message = ((ByteBuf) msg);
        try {
            while (message.isReadable()) {
                System.out.println((char) message.readByte());
                System.out.flush();
            }
        } finally {
            ReferenceCountUtil.release(message);
        }
    }

    /**
     * 当Netty因I/O错误而引发异常时，或者处理程序实现因处理事件时引发异常而引发异常时，将使用Throwable调用exctionCauight()事件处理程序方法。
     * 在大多数情况下，应记录捕获的异常，并在此处关闭与其关联的通道，尽管此方法的实现可能会有所不同，具体取决于您要如何处理异常情况。
     * 例如，您可能希望在关闭连接之前发送带有错误代码的响应消息。
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 当异常发生的时候，关闭connection
        cause.printStackTrace();
        ctx.close();
    }
}
